﻿using IWshRuntimeLibrary;
using Microsoft.Win32;
using Shell32;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;

namespace TileManager {
    public class Shortcut {

        private static WshShellClass ScriptingHostHandle = new WshShellClass();

        /// <summary>
        /// Returns the filename that a shortcut refers to.
        /// </summary>
        /// <param name="Shortcut">The shortcut to check</param>
        /// <returns>The filename as ShellLinkObject or null if the filename couldn't be resolved.</returns>

        public static ShellLinkObject GetShortcutTarget(string Shortcut) {

            Shell ShellHandler = new Shell();
            Shell32.Folder Folder = ShellHandler.NameSpace(Path.GetDirectoryName(Shortcut));
            FolderItem FolderItem = Folder.ParseName(Path.GetFileName(Shortcut));
            if (FolderItem != null) {
                ShellLinkObject ShortcutTarget = (Shell32.ShellLinkObject)FolderItem.GetLink;
                return ShortcutTarget;
            }

            // TODO Check method calls for null
            return null;
        }

        /// <summary>
        /// Changes the icon of a shortcut.
        /// </summary>
        /// <param name="IconFile">The new icon.</param>
        /// <param name="Target">The shortcut that should have its icon changed</param>

        public static void SetShortcutIcon(string IconFile, string Target) {
            Shell ShellHandler = new Shell();
            Shell32.Folder Folder = ShellHandler.NameSpace(Path.GetDirectoryName(Target));
            FolderItem FolderItem = Folder.ParseName(Path.GetFileName(Target));
            if (FolderItem != null) {
                ShellLinkObject ShortcutTarget = (Shell32.ShellLinkObject)FolderItem.GetLink;
                Debug.WriteLine(ShortcutTarget.Path.ToString());
                ShortcutTarget.SetIconLocation(IconFile, 0);
                ShortcutTarget.Save();
            }
        }

        /// <summary>
        /// Changes the icon of a shortcut.
        /// </summary>        
        /// <param name="Target">The shortcut that should have its icon changed</param>
        /// <param name="Index">The index of the icon.</param>

        public static void SetShortcutIcon(string Target, string dllFile, int Index) {



            Shell ShellHandler = new Shell();
            Shell32.Folder Folder = ShellHandler.NameSpace(Path.GetDirectoryName(Target));
            FolderItem FolderItem = Folder.ParseName(Path.GetFileName(Target));
            if (FolderItem != null) {
                ShellLinkObject ShortcutTarget = (Shell32.ShellLinkObject)FolderItem.GetLink;
                Debug.WriteLine(ShortcutTarget.Path.ToString());
                ShortcutTarget.SetIconLocation(dllFile, Index);
                ShortcutTarget.Save();
            }
        }

        /// <summary>
        /// Creates a shortcut (*.lnk) to a given file.
        /// </summary>
        /// <param name="targetFile">The file the shortcut points to.</param>
        /// <param name="targetDirectory">The working directory of the shortcut.</param>        
        /// <param name="destinationPath">The directory where the shortcut will be created.</param>   
        /// <exception cref="UnauthorizedAccessException">Thrown when the the user has insufficient access rights to the destination path.</exception>

        public static void MakeShortcut(string targetFile, string targetDirectory, string destinationPath) {
            destinationPath = Environment.ExpandEnvironmentVariables(destinationPath);
            IWshShortcut Shortcut = (IWshShortcut)ScriptingHostHandle.CreateShortcut(destinationPath + @"\" + Helpers.GetFileDescription(targetFile, targetDirectory, true) + @".lnk");
            Debug.WriteLine("Path: " + targetDirectory + "\\" + targetFile + ".lnk");

            Shortcut.TargetPath = targetDirectory + "\\" + targetFile;
            Shortcut.Description = targetFile;

            try {
                Shortcut.Save();
            }
            catch (UnauthorizedAccessException) {
                throw;
            }
        }

        /// <summary>
        /// Creates a shortcut (*.lnk) to a given file.
        /// </summary>
        /// <param name="TargetFile">The file the shortcut links to.</param>
        /// <param name="TargetDirectory">The working directory of the shortcut.</param>  
        /// <param name="DestinationPath">The path where the shortcut is saved to.</param>  
        /// <param name="Description">The shortcut description/title</param>
        /// <exception cref="UnauthorizedAccessException">Thrown when the the user has insufficient access rights to the destination path.</exception>

        public static void MakeShortcut(string TargetFile, string TargetDirectory, string DestinationPath, string Description) {
            DestinationPath = Environment.ExpandEnvironmentVariables(DestinationPath);
            string FileDescription;

            if (!Description.Equals(Helpers.GetFileDescription(TargetFile, TargetDirectory, false))) {
                FileDescription = Description;
            }
            else {
                FileDescription = Helpers.GetFileDescription(TargetFile, TargetDirectory, true);
            }

            IWshShortcut Shortcut = (IWshShortcut)ScriptingHostHandle.CreateShortcut(DestinationPath + @"\" + FileDescription + @".lnk");
            Debug.WriteLine("Path: " + TargetDirectory + "\\" + TargetFile + ".lnk");

            Shortcut.TargetPath = TargetDirectory + "\\" + TargetFile;
            Shortcut.Description = TargetFile;

            try {
                Shortcut.Save();
            }
            catch (UnauthorizedAccessException) {
                throw;
            }
        }

        /// <summary>
        /// Creates a fake URL shortcut by running the systems' default browser with the actual URL as Argument
        /// </summary>
        /// <param name="Url">The URL the link should point to</param>
        /// <param name="Name">The name of the shortcut</param>
        /// <param name="IconFile">The icon</param>
        /// <param name="TargetPath">The path where the shortcut will be created</param>
        /// <exception cref="UnauthorizedAccessException">Thrown when the the user has insufficient access rights to the destination path.</exception>

        public static void MakeURLShortcut(string Url, string Name, string IconFile, string TargetPath) {

            IWshShortcut Shortcut = (IWshShortcut)ScriptingHostHandle.CreateShortcut(TargetPath + @"\" + Name + @".lnk");

            // Get ProgID from default HTTP handler
            RegistryKey DefaultHttpAssociation = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice");
            string DefaultBrowserProgId = DefaultHttpAssociation.GetValue("ProgId").ToString();

            // Search the ProgID for the actual browser command
            RegistryKey DefaultBrowserRegKey = Registry.ClassesRoot.OpenSubKey(DefaultBrowserProgId + @"\shell\open\command");
            string DefaultBrowserCommand = DefaultBrowserRegKey.GetValue(String.Empty).ToString();

            // Format command string
            DefaultBrowserCommand = DefaultBrowserCommand.Replace("\"", String.Empty);
            DefaultBrowserCommand = DefaultBrowserCommand.Replace("%1", String.Empty);
            DefaultBrowserCommand = DefaultBrowserCommand.Replace("-", String.Empty);
            DefaultBrowserCommand = DefaultBrowserCommand.Trim();

            Shortcut.TargetPath = DefaultBrowserCommand;
            Shortcut.Arguments = Url;

            try {
                Shortcut.Save();
                if (!IconFile.Equals("none")) {
                    SetShortcutIcon(IconFile, TargetPath + @"\" + Name + @".lnk");
                }
            }
            catch (UnauthorizedAccessException) {
                Debug.WriteLine("UAE LINK");
                throw;
            }
        }

        /// <summary>
        /// Invokes the icon selector dialogue for *.dll files. Use with GetShell32Icon(int).
        /// </summary>
        /// <param name="Handle">Main form handle</param>
        /// <returns>int.MaxValue if no icon was selected, or the index of the icon in the file</returns>

        public static int ShowShellIconDialog(IntPtr Handle, string DllPath) {

            int IconIndex = int.MaxValue;
            StringBuilder ShellPath = new System.Text.StringBuilder(DllPath, 500);
            int Retval = NativeMethods.PickIconDlg(Handle, ShellPath, ShellPath.Length + 1, ref IconIndex);

            return IconIndex;
        }

        /// <summary>
        /// Returns the icon of a file.
        /// </summary>
        /// <param name="PathToFile">The file to extract from.</param>
        /// <returns>The extracted icon.</returns>

        public static Icon GetIcon(string PathToFile) {

            Icon FileIcon = Icon.ExtractAssociatedIcon(PathToFile);

            return FileIcon;
        }

        /// <summary>
        /// Retrieves an icon from a *.dll file. Use with ShowShellIconDialog(IntPtr).
        /// </summary>
        /// <param name="Index">The index of the icon inside the file.</param>
        /// <returns>The selected icon</returns>

        public static Icon GetDllIcon(string DllFile, int Index) {

            IntPtr IconIndex = NativeMethods.ExtractIcon(IntPtr.Zero, DllFile, 0);
            Icon ShellIcon = System.Drawing.Icon.FromHandle(IconIndex);
            return ShellIcon;
        }
    }
}
